package com.tcm.day01;

/**
 * Math.random()
 */
public class Code04_random {

    public static void main(String[] args) {

        int k = 100000;
        int count = 0;
        // Math.random() -> [0,1)
        for (int i = 0; i < k; i++) {
            if (Math.random() < 0.6) {
                count++;
            }
        }
        System.out.println("随机数小于0.6的概率是：" + ((double) count / (double) k));

        count = 0;
        for (int i = 0; i < k; i++) {
            if (Math.random() * 8 < 5) {
                count++;
            }
        }
        System.out.println("随机数*8小于5的概率是：" + ((double) count / (double) k));
        System.out.println(((double) 5 / (double) 8));

        // n -> [0,n-1]，n=9
        int[] counts = new int[9];
        for (int i = 0; i < k; i++) {
            int num = (int) (Math.random() * 9);
            counts[num]++;
        }

        for (int i = 0; i < counts.length; i++) {
            System.out.println(i + "出现的次数：" + counts[i]);
        }

        count = 0;
        double x = 0.17;
        for (int i = 0; i < k; i++) {
            if (xToXPower2() < x) {
                count++;
            }
        }
        System.out.println((double) count / (double) k);
        System.out.println(Math.pow(x, 2));

        count = 0;
        int[] arr = new int[8];
        for (int i = 0; i < k; i++) {
            arr[g()]++;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(i + "出现的次数：" + arr[i]);
        }
    }

    // 返回[0,1)的一个小数
    // 任意的x，x属于[0,1)，[0,x)范围上的数出现概率由原来的x调整成x的平方
    // 返回一个数的概率是x，返回另一个数的概率也是x，加上Math.max()要使得两边都要满足这个概率，则是x的平方
    // Math.min()与Math.max()相反，逆向思维返回的概率是1-(1-x)^2
    // 满足[0,1)范围的概率是x，不满足[0,1)范围的概率是1-x，求最小值则为1-(1-x)^2
    //
    public static double xToXPower2() {
        return Math.max(Math.random(), Math.random());
    }

    // 从1~5随机到1~7随机
    // a~b随机可以得到c~d随机
    // f1函数1~5随机
    public static int f1() {
        return (int) (Math.random() * 5) + 1;
    }

    // 利用f1实现0~1随机
    // 1~2为0,4~5为1,3重新生成
    public static int f2() {
        int ans = 0;
        do {
            ans = f1();
        } while (ans == 3);
        return ans > 3 ? 1 : 0;
    }

    // 1~7随机基于0~6随机再加1
    // 0~6需要3个二进制位表示
    public static int f3() {
//                    100          10          1
        int ans = (f2() << 2) + (f2() << 1) + f2();
        return ans;
    }

    // 0~6随机数
    // 结果为7重新生成
    public static int f4() {
        int ans = 0;
        do {
            ans = f3();
        } while (ans == 7);
        return ans;
    }

    // 1~7随机数
    public static int g() {
        return f4() + 1;
    }

    // 给定一个函数，0和1是固定概率返回但不是等概率返回
    public static int x1() {
        return Math.random() < 0.84 ? 0 : 1;
    }

    // 0和1等概率返回
    public static int x2() {
        // 返回0的概率是P，返回1的概率是1-P，只有两次返回0和1或1和0才是等概率返回
        int ans = 0;
        do {
            ans = x1();
        } while (ans == x1());
        return ans;
    }
}
